import axios from 'axios';
import {
  getToken
} from '@/utils/auth.js';
import {
  loading,
  message
} from '@/utils/base/common.js';

const OCTET_STREAM = 'application/octet-stream'
const MS_EXCEL = 'application/vnd.ms-excel'
const HEADERS = {
        Accept: 'application/json',
        'Content-Type': 'application/json; charset=utf-8', // 后端ssm框架接收json类型
        // TODO 由于后台报401，暂时不进行token验证
//      'Authorization': 'Bearer ' + getToken(),
        withCredentials: false, // 当前请求为跨域类型时是否在请求中协带cookie。
      }

/* 
  ## 使用axios下载文件：
    1. 前端 axios 的 config 配置 responseType: 'blob' （关键）
    2. 服务端读取文件，以 content-type: 'application/octet-stream' 的格式返回前端（二进制流数据,如常见的文件下载)）
    3. 前端接收到数据后，使用 Blob 来接收数据，并且创建a标签进行下载
    
  ## AJAX无法下载文件的原因：
          下载其实是浏览器的内置事件，浏览器的 GET请求（frame、a）、 POST请求（form）具有如下特点：
      response会交由浏览器处理
      response内容可以为二进制文件、字符串等
      
          但是AJAX请求不一样：
      response会交由 Javascript 处理
      response内容只能接收字符串才能继续处理
          因此，AJAX本身无法触发浏览器的下载功能。

*/

/**
 * 下载-Get
 */
export function downloadGet(that_, url, params) {
  // 加载中
  const myLoading = loading(that_, '正在下载，请稍候!')
  
  axios.get(
    url,
    {
      params: params,
      headers: HEADERS,
      responseType: 'blob', // 关键，响应类型为流
      timeout: 20000
    }
  ).then((response) => {
    // 加载中 关闭
    myLoading.close(); 
    // 处理结果
    convertRes2Blob(response, OCTET_STREAM)
  }).catch(err => {
    // 加载中 关闭
    myLoading.close(); 
    message(that_, 'error', 2, '下载数据失败!')
  })
}

/**
 * 下载-Post
 */
export function downloadPost(that_, url, data) {
  // 加载中
  const myLoading = loading(that_, '正在下载，请稍候!')
  
  axios.post(
    url,
    data,
    {
      headers: HEADERS,
      responseType: 'blob',
      timeout: 20000
    }
  ).then((response) => {
    // 加载中 关闭
    myLoading.close(); 
    // 处理结果
    convertRes2Blob(response, OCTET_STREAM)
  }).catch(err => {
    console.error(err)
    // 加载中 关闭
    myLoading.close(); 
    message(that_, 'error', 2, '下载数据失败!')
  })
}


/**
 * 导出Excel-Get
 */
export function exportExcelGet(that_, url, params) {
  // 加载中
  const myLoading = loading(that_, '正在导出，请稍候!')
  
  axios.get(
    url,
    {
      params: params,
      headers: HEADERS,
      responseType: 'blob', // 关键，响应类型为流
      timeout: 20000
    }
  ).then((response) => {
    // 加载中 关闭
    myLoading.close(); 
    // 处理结果
    convertRes2Blob(response, MS_EXCEL)
  }).catch(err => {
    // 加载中 关闭
    myLoading.close(); 
    message(that_, 'error', 2, '导出数据失败!')
  })
}

/**
 * 导出Excel- Post
 */
export function exportExcelPost(that_, url, data) {
  // 加载中
  const myLoading = loading(that_, '正在导出，请稍候!')
  
  axios.post(
    url,
    data,
    {
      headers: HEADERS,
      responseType: 'blob',
      timeout: 20000
    }
  ).then((response) => {
    // 加载中 关闭
    myLoading.close(); 
    // 处理结果
    convertRes2Blob(response, MS_EXCEL)
  }).catch(err => {
    // 加载中 关闭
    myLoading.close(); 
    message(that_, 'error', 2, '导出数据失败!')
  })
}


/**
 * 处理返回数据流
 */
function convertRes2Blob(response, myType) {
  // 提取文件名（从response的headers中获取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 设置的文件名;）
  const fileName = response.headers['content-disposition'].match(
    /filename=(.*)/
  )[1]
  // 这里res.data是返回的blob对象。将二进制流转为blob
  const blob = new Blob([response.data], { type: myType })
  if (typeof window.navigator.msSaveBlob !== 'undefined') {
    // 兼容IE，window.navigator.msSaveBlob：以本地方式保存文件
    window.navigator.msSaveBlob(blob, decodeURI(fileName))
  } else {
    // 创建下载链接，指向File对象或者Blob对象的地址
    const blobURL = window.URL.createObjectURL(blob)
    // 创建a标签，用于跳转至下载链接
    const tempLink = document.createElement('a')
    tempLink.style.display = 'none'
    tempLink.href = blobURL
    tempLink.setAttribute('download', decodeURI(fileName))
    // 兼容：某些浏览器不支持HTML5的download属性
    if (typeof tempLink.download === 'undefined') {
      tempLink.setAttribute('target', '_blank')
    }
    // 挂载a标签
    document.body.appendChild(tempLink)
    // 点击下载
    tempLink.click()
    // 下载完成移除元素
    document.body.removeChild(tempLink)
    // 释放blob对象 URL地址
    window.URL.revokeObjectURL(blobURL)
  }
}